/**
 * 自动刷新Token，
 *
 * 当刷新token过程中，需要token的接口处于等待队列
 */

import { SilenceAuthLogin } from "@/api/login";
import type { TRequestOptins, TRequestParams } from "./request";
import Taro from "@tarojs/taro";

// 尝试次数
let count = 0;
// 单次最大尝试次数
const maxAuthTimes = 2;

// 单个阶段，尝试次数，达到2次后，不再尝试刷新，等手动登录；
let compensationCount = 0;

// 重置
const resetCount = () => (count = 0);

// 是否正在登录授权
let isAuthorizing = false;

// 等待队列
const fetchStackList: Array<Function> = [];

// 登录
const authLogin = (rejectData?) => {
  console.log("=====count", isAuthorizing, count, compensationCount);

  if (count >= maxAuthTimes) {
    // @ts-expect-error
    fetchStackList.forEach((fn) => fn.reject(rejectData));
    resetCount();
    // 超过重连次数后，reject所有请求
    isAuthorizing = false;
    fetchStackList.length = 0;
  } else {
    count++;

    console.log("====第" + count + "次自动登录");

    SilenceAuthLogin().then(
      () => {
        console.log("===登录成功");
        // 登录成功，
        resetCount();
        compensationCount = 0;
        isAuthorizing = false;
        fetchStackList.forEach((fn) => fn());
        fetchStackList.length = 0;
      },
      // catch: 再自行一次
      (error) => {
        console.log("error自动登录失败", error);

        if (error?.forceLogin) {
          // 非强制登录状态下，再做尝试
          count = maxAuthTimes;

          console.log("====此处应该停止，应只打印一次");
          authLogin({ msg: "请登录" });

          Taro.reLaunch({ url: "/pages/login/index" });
        } else {
          // 延迟1s再尝试
          setTimeout(() => {
            authLogin();
          }, 1000);
        }
      }
    );
  }
};

// 把后续请求放入队列
const pushFetchToStack = (
  request,
  requestParams: TRequestParams,
  requestOptions: TRequestOptins | undefined = undefined,
  resolve: any,
  reject: any
) => {
  const fetch = () =>
    toFetch(request, requestParams, requestOptions, resolve, reject);

  fetch.reject = reject;
  // 存储当前请求信息
  fetchStackList.push(fetch);
};

//
const toFetch = (
  request,
  requestParams,
  requestOptions,
  resolve,
  reject,
  flag?: boolean
) => {
  request(requestParams, requestOptions).then(resolve, (err) => {
    if (compensationCount < 2 && err?.code === 401) {
      if (flag) {
        pushFetchToStack(
          request,
          requestParams,
          requestOptions,
          resolve,
          reject
        );
      }
      console.log("toFetch:isAuthorizing", isAuthorizing, requestParams);

      if (!isAuthorizing) {
        // token过期，待重新登录授权
        isAuthorizing = true;
        // 记录单次阶段次数
        compensationCount++;
        authLogin();
      }
    } else {
      reject(err);
    }
  });
};

// 刷新Token请求出入函数
const autoRefreshAuthTokenFetch = (
  request,
  requestParams: TRequestParams,
  requestOptions?: TRequestOptins
) => {
  return new Promise((resolve, reject) => {

    // 当前请求需要token && 正在登录授权中
    if (
      requestOptions?.tokenAuth !== false &&
      isAuthorizing &&
      compensationCount < 2
    ) {
      // 存储当前请求信息
      pushFetchToStack(request, requestParams, requestOptions, resolve, reject);
    } else {
      // 不需要token || 有token
      toFetch(request, requestParams, requestOptions, resolve, reject, true);
    }
  });
};

export default autoRefreshAuthTokenFetch;
